package thread;

import java.io.File;
import java.io.IOException;

import org.apache.commons.io.FileUtils;

public class ThreadSynchorized {
	static OutPut output = new OutPut();
	static {
		FileUtils.deleteQuietly(new File("D:/java/workspace/ThreadTest/threadtest2.log"));
	}

	public static void main(String[] args) {

		// 同一方法，不同线程的互斥
		// thread1与thread2可同步互斥
		MyTherad1 mytherad1 = new MyTherad1();
		Thread thread1 = new Thread(mytherad1);

		MyTherad2 mytherad2 = new MyTherad2();
		Thread thread2 = new Thread(mytherad2);
		thread1.start();
		thread2.start();

		// 不同线程不同方法的同步互斥
		// thread与thread3可同步互斥,
		/*MyTherad mytherad = new MyTherad();
		Thread thread = new Thread(mytherad);

		MyTherad3 mytherad3 = new MyTherad3();
		Thread thread3 = new Thread(mytherad3);

		thread.start();
		thread3.start();*/
	}

}

/**
 * synchronized 排他性的对象选取： 如一个门进去需有一个门栓，任何一个对象都可以作为一个门栓
 * 如果这个栓子没被别人拿走，就可以进入，如果被人拿走，就需要等待 互斥必须使用同一个对象
 * 
 */
class OutPut {
	public void output(String name) throws IOException {
		synchronized (OutPut.class) {
			for (int i = 0; i < name.length(); i++) {
				System.out.print(name.charAt(i));
			}
			System.out.println();
			FileUtils.writeStringToFile(new File("D:/java/workspace/ThreadTest/threadtest2.log"),
			        name + "\r\n", true);
		}

	}

	public static synchronized void output3(String name) throws IOException {
		for (int i = 0; i < name.length(); i++) {
			System.out.print(name.charAt(i));
		}
		System.out.println();
		FileUtils.writeStringToFile(new File("D:/java/workspace/ThreadTest/threadtest2.log"), name
		        + "\r\n", true);
	}

	/**如果每个线程都都使用OutPut output = new OutPut()方法进行创建output对象，
	 * 则此方法无法实现互斥，由于output2使用的是this对象互斥， 而OutPut对象是新new的，不是同一个对象
	 * @throws IOException 
	 */
	public synchronized void output2(String name) throws IOException {
		for (int i = 0; i < name.length(); i++) {
			System.out.print(name.charAt(i));
		}
		System.out.println();
		FileUtils.writeStringToFile(new File("D:/java/workspace/ThreadTest/threadtest2.log"),
		        name + "\r\n", true);
	}
	
	public synchronized void output4(String name) throws IOException {
		for (int i = 0; i < name.length(); i++) {
			System.out.print(name.charAt(i));
		}
		System.out.println();
		FileUtils.writeStringToFile(new File("D:/java/workspace/ThreadTest/threadtest2.log"),
		        name + "\r\n", true);
	}

}

class MyTherad1 implements Runnable {

	@Override
	public void run() {
		// OutPut output = new OutPut();

		while (true) {
			// output.output2("xiongfei");
			try {
	            ThreadSynchorized.output.output2("&xiongfei");
            } catch (Exception e1) {
	            e1.printStackTrace();
            }
		}
	}

}

class MyTherad2 implements Runnable {

	@Override
	public void run() {
		// OutPut output = new OutPut();
		while (true) {
			// output.output2("@fengyuan");
			try {
	            ThreadSynchorized.output.output4("@fengyuan");
            } catch (Exception e) {
	            e.printStackTrace();
            }
			/*try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}*/
		}
	}

}

class MyTherad implements Runnable {

	@Override
	public void run() {
		while (true) {
			try {
				ThreadSynchorized.output.output("&xiongyujia");
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

}

class MyTherad3 implements Runnable {

	@Override
	public void run() {
		while (true) {
			try {
	            OutPut.output3("@zoufen");
            } catch (IOException e) {
	            e.printStackTrace();
            }
		}
	}
}
